
/*
 * Hlpay-Plus aggregate payment system. Copyright
 * (c) 2022-2023 Hlpay Team Copyright has the right of final interpretation.
 */

package com.hlkj.pay.service.admin.impl;

import java.util.Collections;
import java.util.List;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hlkj.framework.caches.service.RedisTemplateService;
import com.hlkj.framework.common.pojo.LocalContext;
import com.hlkj.framework.common.pojo.LocalRequest;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.hlkj.pay.common.constants.AdminRedisConstant;
import com.hlkj.pay.dto.LocalAdminUserRequest;
import com.hlkj.pay.dto.admin.PermissionQueryDto;
import com.hlkj.pay.infrastructure.mapper.admin.PermissionMapper;
import com.hlkj.pay.infrastructure.model.admin.PermissionDO;
import com.hlkj.pay.service.admin.IPermissionService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.StringUtil;

/**
 * @author HlpayTeam
 * @date 2024/09/01 15:14
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class PermissionServiceImpl implements IPermissionService {

    private final PermissionMapper permissionMapper;

    private final RedisTemplateService redisTemplateService;

    @Override
    public List<PermissionDO> queryRolePermission(List<String> roleCodes) {
        PermissionQueryDto permissionQueryDto = new PermissionQueryDto();
        permissionQueryDto.setPermissionCodeList(roleCodes);
        return queryList(permissionQueryDto);
    }

    @Override
    public List<PermissionDO> queryAllPermission(Integer sysType) {
        String permissionKey = permissionKey(sysType);
        List<Object> objects = redisTemplateService.rangeList(permissionKey);
        if (CollectionUtils.isNotEmpty(objects)) {
            if (log.isDebugEnabled()) {
                log.debug("queryAllPermission cache");
            }
            Object object = objects.get(0);
            return (List<PermissionDO>) object;
        }
        PermissionQueryDto permissionQueryDto = new PermissionQueryDto();
        permissionQueryDto.setSysType(sysType);
        List<PermissionDO> permissionList = queryList(permissionQueryDto);
        if (CollectionUtils.isEmpty(permissionList)) {
            return Collections.emptyList();
        }
        redisTemplateService.lPushAll(permissionKey, AdminRedisConstant.PERMISSION_EXPIRE_TIME.longValue(), permissionList);
        return permissionList;
    }

    @Override
    public PermissionDO queryParentPermission(String parentCode) {
        PermissionQueryDto permissionQueryDto = new PermissionQueryDto();
        permissionQueryDto.setParentCode(parentCode);
        return queryOne(permissionQueryDto);
    }

    @Override
    public PermissionDO queryMaxPermission(String parentCode, Integer type) {
        PermissionQueryDto permissionQueryDto = new PermissionQueryDto();
        permissionQueryDto.setParentCode(parentCode);
        permissionQueryDto.setType(type);
        return permissionMapper.selectLatestOne(permissionQueryDto);
    }

    @Override
    public PermissionDO queryPermissionByCode(String permissionCode) {
        PermissionQueryDto permissionQueryDto = new PermissionQueryDto();
        permissionQueryDto.setPermissionCode(permissionCode);
        return queryOne(permissionQueryDto);
    }

    @Override
    public PermissionDO queryParentPermissionByName(String permissionName, Integer type, Integer sysType) {
        PermissionQueryDto permissionQueryDto = new PermissionQueryDto();
        permissionQueryDto.setName(permissionName);
        permissionQueryDto.setType(type);
        permissionQueryDto.setSysType(sysType);
        return queryOne(permissionQueryDto);
    }

    @Override
    public List<PermissionDO> queryPermissionList(PermissionQueryDto permissionQueryDto) {
        return queryList(permissionQueryDto);
    }

    @Override
    public PageResult<PermissionDO> queryPermissionPage(PermissionQueryDto permissionQueryDto) {
        return permissionMapper.selectPage(permissionQueryDto, buildPermissionWrapper(permissionQueryDto));
    }

    @Override
    public void add(PermissionDO permissionDO) {
        String permissionKey = permissionKey(permissionDO.getSysType());
        permissionMapper.insert(permissionDO);
        redisTemplateService.del(permissionKey);
    }

    @Override
    public void update(PermissionDO updatePermissionDO) {
        String permissionKey = permissionKey(updatePermissionDO.getSysType());
        permissionMapper.updateById(updatePermissionDO);
        redisTemplateService.del(permissionKey);

    }

    @Override
    public PermissionDO queryParentPermissionById(Long id) {
        PermissionQueryDto permissionQueryDto = new PermissionQueryDto();
        permissionQueryDto.setId(id);
        return queryOne(permissionQueryDto);
    }

    @Override
    public void delete(Long id, Integer sysType) {
        permissionMapper.deleteById(id);
        String permissionKey = permissionKey(sysType);
        redisTemplateService.del(permissionKey);
    }

    public List<PermissionDO> queryList(PermissionQueryDto permissionQueryDto) {
        return permissionMapper.selectList(buildPermissionWrapper(permissionQueryDto));
    }

    String permissionKey(Integer sysType) {
        return AdminRedisConstant.PERMISSION + ":" + sysType;
    }

    public PermissionDO queryOne(PermissionQueryDto permissionQueryDto) {
        LambdaQueryWrapper<PermissionDO> lambdaQueryWrapper = buildPermissionWrapper(permissionQueryDto);
        lambdaQueryWrapper.last(" limit 1");
        return permissionMapper.selectOne(lambdaQueryWrapper);
    }

    /**
     * 查询条件封装
     * 
     * @param permissionQueryDto
     * @return
     */
    LambdaQueryWrapper<PermissionDO> buildPermissionWrapper(PermissionQueryDto permissionQueryDto) {
        if (permissionQueryDto.getSysType() == null) {
            LocalRequest localRequest = LocalContext.get();
            if (localRequest instanceof LocalAdminUserRequest) {
                LocalAdminUserRequest localAdminUserRequest = (LocalAdminUserRequest) localRequest;
                permissionQueryDto.setSysType(localAdminUserRequest.getQuerySysType());
            }
        }
        LambdaQueryWrapperX<PermissionDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.inIfPresent(PermissionDO::getCode, permissionQueryDto.getPermissionCodeList());
        queryWrapper.eqIfPresent(PermissionDO::getCode, permissionQueryDto.getPermissionCode());
        queryWrapper.eqIfPresent(PermissionDO::getParentCode, permissionQueryDto.getParentCode());
        queryWrapper.inIfPresent(PermissionDO::getParentCode, permissionQueryDto.getParentPermissionCodeList());
        queryWrapper.eqIfPresent(PermissionDO::getType, permissionQueryDto.getType());
        queryWrapper.eqIfPresent(PermissionDO::getSysType, permissionQueryDto.getSysType());
        queryWrapper.eqIfPresent(PermissionDO::getName, permissionQueryDto.getName());
        queryWrapper.eqIfPresent(PermissionDO::getId, permissionQueryDto.getId());
        queryWrapper.notInIfPresent(PermissionDO::getCode, permissionQueryDto.getNotInCode());
        queryWrapper.likeRight(StringUtil.hasText(permissionQueryDto.getLikePermissionCode()), PermissionDO::getCode, permissionQueryDto.getLikePermissionCode());
        if (permissionQueryDto.getRoot() != null) {
            if (permissionQueryDto.getRoot()) {
                queryWrapper.and(wrapper -> wrapper.isNull(PermissionDO::getParentCode) // name IS NULL
                        .or() // OR
                        .eq(PermissionDO::getParentCode, ""));
            }
            else {
                queryWrapper.isNotNull(PermissionDO::getParentCode);
            }
        }
        return queryWrapper;
    }

}
